#pragma once

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/epoll.h>
#include "Log.hpp"
#include "Err.hpp"

static const int default_epfd = -1;
static const int default_epoll_size = 128;

class Epoller
{
public:
    Epoller(): _epfd(default_epfd)
    {}
    ~Epoller()
    {
        if(_epfd != default_epfd) close(_epfd);
    }
public:
    void Create()
    {
        _epfd = epoll_create(default_epoll_size);
        if(_epfd < 0)
        {
            logMessage(FATAL, "epoll create error: %d, indicate: %s", errno, strerror(errno));
            exit(EPOLL_CREATE_ERROR);
        }
    }
    // user -> kernel
    bool AddEvent(int sockfd, uint32_t events)
    {
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd = sockfd;

        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);
        return n == 0;
    }
    bool Control(int sockfd, uint32_t events, int op)
    {
        int n = 0;
        if(op == EPOLL_CTL_MOD)
        {
            struct epoll_event ev;
            ev.data.fd = sockfd;
            ev.events = events;
            n = epoll_ctl(_epfd, op, sockfd, &ev);
        }
        else if(op == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, op, sockfd, nullptr);
        }
        else n = -1;

        return n == 0;
    }
    // kernel -> user
    int Wait(struct epoll_event revs[], int ev_num, const int timeout)
    {
        int n = epoll_wait(_epfd, revs, ev_num, timeout);
        return n;
    }

    void Close()
    {
        if(_epfd != default_epfd) close(_epfd);
    }
private:
    int _epfd;// epoll模型
};